#include <iostream>
#include <cmath>
#include "StarAndMap.h""
using namespace std;

double distance(int x1, int y1, int x2, int y2)
{
    int a = x1 - x2;
    int b = y1 - y2;
    return sqrt(a * a + b * b);
}

Map::Map(int a,int b)//星系数，文明数
{
    this->n_stars = a;
    s = new star[a];
    this->n_civ = b;
    c = new civ[b];
    for (int i = 0; i < b; i += 1)
    {
        c[i].own = new star * [a];
        c[i].observed = new star * [a];
        c[i].num=i;
        c[i].icon_set();
    }
}

void Map::mapgen(int a)
{
    srand(time(NULL));
    for (int i = 0; i < a; i += 1)
    {
        if (i == 0)
        {
            s[i].x = abs(rand() % length);
            s[i].y = abs(rand() % height);
            s[i].n = i;
            s[i].res = rand() % 5 + 1;
            s[i].poplim = rand() % 90 + 10;
            s[i].owned=0;
        }
        else
        {
            s[i].n = i;
            s[i].res = rand() % 5 + 1;
            s[i].poplim = rand() % 90 + 10;
            s[i].owned=0;
            int token = 0;
            while (token == 0)
            {
                int temp_x = abs(rand() % length);
                int temp_y = abs(rand() % height);
                int token1 = 0;
                for (int i1 = 0; i1 < i && token1 == 0; i1 += 1)
                {
                    if (distance(temp_x, temp_y, s[i1].x, s[i1].y) < 20)
                    {
                        token1 = 1;
                    }
                }
                if (token1 == 1)
                {
                    token1 = 0;
                    continue;
                }
                if (token1 == 0)
                {
                    s[i].x = temp_x;
                    s[i].y = temp_y;
                    token = 1;
                }
            }
            token = 0;
        }
    }
}

void Map::civdis(int a, int b)//星系数，文明数
{
    srand(time(NULL));
    int* assigned = new int[a];
    for (int i = 0; i < b; )
    {
        int temp = rand() % a;
        int token;
        token = 0;
        for (int i1 = 0; i1 < i&&token==0; i1 += 1)
        {
            if (assigned[i1] == temp)
            {
                token = 1;
            }
        }
        if (token == 0)
        {
            c[i].own[0] = &s[temp];
            c[i].owned+=1;
            assigned[i] = temp;
            s[temp].pop=s[temp].poplim/2;
            s[temp].owned=1;
            i += 1;
        }
        token = 0;
    }
    delete[] assigned;
}



star::star():button_icon(":/new/images/images/HugeStar.png")
{
    natural_value=poplim/20+res;
}
void star::change()
{
    if(owned==0)
    {
        if(selected==0)
        {
            QIcon *newIcon=new QIcon (":/new/images/images/icon_1.png");
            this->setIcon(*newIcon);
            delete newIcon;
            selected=1;
        }
        else
        {
            QIcon *newIcon=new QIcon (":/new/images/images/HugeStar.png");
            this->setIcon(*newIcon);
            delete newIcon;
            selected=0;
        }
    }
}

void civ::nextTurn()
{
    balance();
    expand();
    repaint();
}

void Map::observe()
{
    for(int i=0;i<n_civ;i+=1)//遍历所有文明
    {
        int temp=0;//文明可观测星系总数
        for(int i1=0;i1<c[i].owned;i1+=1)//遍历单个文明的所有星系
        {
            for(int i2=0;i2<n_stars;i2+=1)//遍历全图星系
            {
                //if(s[i2].owned==1)
                //{
                    //continue;
                //}
                int token=0;
                for(int i3=0;i3<c[i].owned&&token==0;i3+=1)//遍历单个文明所有星系，确认待测星系不属于此文明
                {
                    if(c[i].own[i3]->n==s[i2].n)
                    {
                        token=1;
                    }
                }
                for(int i3=0;i3<temp&&token==0;i3+=1)//遍历单个文明所有已观测星系，确认待测星系未被观测
                {
                    if(c[i].observed[i3]->n==s[i2].n)
                    {
                        token=1;
                    }
                }
                if(token==0)
                {
                    if(distance(c[i].own[i1]->x,c[i].own[i1]->y,s[i2].x,s[i2].y)<70)
                    {
                        c[i].observed[temp]=&s[i2];
                        temp+=1;
                    }
                }
                token=0;
            }
        }
        for(int i1=temp;i1<n_stars;i1+=1)//清理残余指针
        {
            c[i].observed[i1]=NULL;
        }
        c[i].observe=temp;
        temp=0;
    }
}
void civ::balance()
{
    for(int i1=0;i1<owned;i1+=1)
    {
        resources+=(own[i1]->pop)*(own[i1]->res);
    }
};//获取结余资源
void civ::repaint()//给星系换颜色
{
    for(int i1=0;i1<owned;i1+=1)
    {
        own[i1]->setIcon(*I);
    }
};

void civ::expand()//扩张
{
    srand(time(NULL));
    if(observe==0)
    {
        return;
    }
    int **candidate=new int*[observe];
    for(int i=0;i<observe;i+=1)
    {
        candidate[i]=new int[2];
    }
    int n_candidate=0;
    for(int i=0;i<observe;i+=1)
    {
        if(observed[i]->owned==0)
        {
            candidate[n_candidate][0]=i;
            candidate[n_candidate][1]=(observed[i]->poplim / 20 + observed[i]->res) / 2 + (rand() % (observed[i]->poplim / 20 + observed[i]->res)) / 2;
            n_candidate+=1;
        }
    }
    for(int i=0;i<n_candidate;i+=1)
    {
        for(int i1=0;i1<n_candidate-1;i1+=1)
        {
            if(candidate[i1][1]<candidate[i1+1][1])
            {
                int temp1=candidate[i1][0];
                int temp2=candidate[i1][1];
                candidate[i1][0]=candidate[i1+1][0];
                candidate[i1][1]=candidate[i1+1][1];
                candidate[i1+1][0]=temp1;
                candidate[i1+1][1]=temp2;
            }
        }
    }
    if(resources>=100&&n_candidate>0)
    {
        resources-=100;
        own[owned]=observed[candidate[0][0]];
        observed[candidate[0][0]]->owned=1;
        owned+=1;
    }
    for(int i=0;i<observe;i+=1)
    {
        delete[] candidate[i];
    }
    delete[] candidate;
};
